<?php

/**
 * Classe Destinada à distribuir as chamadas entre os atendentes de telemarketing
 * @property usuario_loginModel $uobj <p>Instância da classe usuario_loginModel</p>
 * @property visitacompModel    $md   <p>Instância da classe visitacompModel</p>
 * 
 * @property array $atendentes   <p>Lista de todos os atendentes disponíveis</p>
 * @property array $semAtendente <p>Lista de visitas que não possuem nenhum atendente</p>
 * @property array $naoAtendidos <p>Lista que contém o código do atendente e o número de ligações pendentes</p>
 * @property int   $total        <p>Número total de chamadas pendentes que cada atendente deverá receber</p>
 */
class distribuirChamadas extends Object{

    protected $uobj         = null;
    private   $md           = null;
    private   $atendentes   = array();
    private   $semAtendente = array(); 
    private   $naoAtendidos = array();
    private   $total        = 0;
    
    public function __construct() {
        $this->LoadModel('usuario/login', 'uobj');
    }
    
    /**
     * Inicializa a classe
     * @param venda_visitacompModel $obj Cópia da instância da classe visitaComp
     */
    public function init($obj){
        $this->md = $obj;
    }
    
    /**
     * Distribui todas as chamadas pendentes entre os funcionários do telemarketing
     * @return bool true caso consiga inserir todas as chamadas, false caso o contrário
     */
    public function distribuir(){
        $this->atendentes   = $this->getTelemarketingWorkers();
        if(empty($this->atendentes)){
            $this->setErrorMessage('Não existe nenhum atendente de telemarketing cadastrado no sistema');
            return false;
        }
        
        $this->semAtendente = $this->getVisitasSemAtendente();
        if(empty($this->semAtendente)) return true;
        
        $this->naoAtendidos = $this->getNaoAtendidos();
        
        $this->total = $this->getTotalPorAtendente();
        return $this->insert();
    }
    
    /**
     * Distribui no banco de dados as chamadas divididas para os atendentes
     * @return bool true caso consiga inserir todas as chamadas, false caso o contrário
     */
    private function insert(){
        foreach($this->semAtendente as $sat){
            $post['venda_visitacomp_telemkt'] = $this->getAtendente($this->atendentes, $this->naoAtendidos, $this->total);
            if(!$this->md->editar(array($sat['venda_funcionario_cod'], $sat['venda_visita_cod']), $post)){
                $this->setErrorMessage($this->md->getErrorMessage());
                return false;
            }
        }
        return true;
    }
    
    /**
     * Procura no banco de dados todos os usuários com o perfil de telemarketing
     * @return array Lista de usuários do telemarketing
     */
    private function getTelemarketingWorkers(){
        $out = array();
        $var = $this->uobj->selecionar(array("cod_usuario"), "cod_perfil = '".TELEMARKETING."'");
        if(empty($var)) return array();
        foreach($var as $v){
            $out[] = $v['cod_usuario'];
        }
        return $out;
    }
    
    /**
     * Procura no banco de dados todas as visitas que não possuem um atendente
     * @return array Array contendo as visitas sem atendente
     */
    private function getVisitasSemAtendente(){
        return $this->md->selecionar(
                array("venda_funcionario_cod", "venda_visita_cod"), 
                "venda_visitacomp_telemkt IS NULL"
        );
    }
    
    /**
     * Procura no banco de dados todas as chamadas pendentes que possuem um atendente
     * @return array Array contendo as chamadas pendentes
     */
    private function getNaoAtendidos(){
        $at = "'".implode("','", $this->atendentes)."'";
        $var = $this->md->selecionar(
                array("venda_visitacomp_telemkt", "count(*) as total"),
                "venda_visitacomp_telemkt IN($at) AND venda_visitacomp_status = 'pendente'
                GROUP BY venda_visitacomp_telemkt
                "
        );
        //echo $this->db->getSentenca();
        if(empty($var)) return array();
        
        $out = array();
        foreach($var as $v) $out[$v['venda_visitacomp_telemkt']] = $v;
        return $out;
    }
    
    /**
     * Calcula o máximo de ligacoes que um atendente deve possuir
     * @return int Número máximo de ligações
     */
    private function getTotalPorAtendente(){
        $total = count($this->semAtendente);
        foreach($this->naoAtendidos as $na){
            $total += $na['total'];
        }
        return ceil($total/count($this->atendentes));
    }
    
    /**
     * Seleciona um dos atendentes para uma chamada
     * @return int Código de um atendente
     */
    private function getAtendente(){
        
        //sorteia um atendente
        $i        = mt_rand (0 , count($this->atendentes) - 1);
        $cod_user = $this->atendentes[$i];
        
        //verifica se este atendente já possui alguma chamada não atendida, caso não possua, seta como zero
        if(!array_key_exists($cod_user, $this->naoAtendidos)){
            $this->naoAtendidos[$cod_user] = array('venda_visitacomp_telemkt' => $cod_user, 'total' => 0);
        }
        
        //se usuário já está com o limite máximo por atendente, então o remove da lista e sorteia outro atendente
        if($this->naoAtendidos[$cod_user]['total'] > $this->total){
            unset($this->atendentes[$i]);
            unset($this->naoAtendidos[$cod_user]);
            return $this->getAtendente($this->atendentes, $this->naoAtendidos, $this->total);
        }
        
        //adiciona o atendimento ao atendente
        $this->naoAtendidos[$cod_user]['total']++;
        
        //retorna o código de usuário do atendente
        return $cod_user;
    }
    
}
?>